import axios, { AxiosError } from 'axios'
import * as https from 'https'
import { WPSContext } from './WPSContext'
import { WPSError } from './WPSError'
// import { logger } from '../../src/ins'

const agent = new https.Agent({ rejectUnauthorized: false })

export interface WPSParams {
  [key: string]: any
}

export interface WPSHeader {
  [key: string]: any
}

export class WPSRequest {
  ctx: WPSContext
  headers: WPSHeader = {}

  constructor(ctx: WPSContext) {
    this.ctx = ctx
  }

  private WPSError(error: any) {
    if (error.response) {
      const status = error.response.status || 500
      let { code, msg } = error.response.data
      code = code || 1
      msg = msg || 'serverError'
      throw new WPSError(status, code, msg, error)
    }
    const message = error.message || 'error'
    return new WPSError(500, 1, message, error)
  }

  async get<T>(
    url: string,
    params?: WPSParams
  ) {
    url = this.query(url, params as WPSParams)
    const sign = this.ctx.sign('GET', url)
    url = this.ctx.abs(url)

    try {
      const ret = await axios.get(url, {
        headers: { ...this.headers, ...sign },
        httpsAgent: agent
      })
      return ret.data as T
    } catch (error) {
      // logger.error(url, error.response?.data)
      throw this.WPSError(error)
    }
  }

  async post<T>(
    url: string,
    params?: WPSParams,
    data = {}
  ) {
    url = this.query(url, params as WPSParams)
    const body = this.ctx.stringify(data)
    const sign = this.ctx.sign('POST', url, body)
    url = this.ctx.abs(url)

    console.log(sign)
    console.log(url)
    console.log(body)

    try {
      const ret = await axios.post(url, body, {
        headers: { ...this.headers, ...sign },
        httpsAgent: agent
      })
      return ret.data as T
    } catch (error) {
      // logger.error(url, body, error.response?.data)
      throw this.WPSError(error)
    }
  }

  async put<T>(
    url: string,
    params?: WPSParams,
    data = {}
  ) {
    url = this.query(url, params as WPSParams)
    const body = this.ctx.stringify(data)
    const sign = this.ctx.sign('PUT', url, body)
    url = this.ctx.abs(url)

    try {
      const ret = await axios.put(url, body, {
        headers: { ...this.headers, ...sign },
        httpsAgent: agent
      })
      return ret.data as T
    } catch (error) {
      // logger.error(url, body, error.response?.data)
      throw this.WPSError(error)
    }
  }

  async delete<T>(
    url: string,
    params?: WPSParams
  ) {
    url = this.query(url, params as WPSParams)
    const sign = this.ctx.sign('DELETE', url)
    url = this.ctx.abs(url)

    try {
      const ret = await axios.delete(url, {
        headers: { ...this.headers, ...sign },
        httpsAgent: agent
      })
      return ret.data as T
    } catch (error) {
      // logger.error(url, error.response?.data)
      throw this.WPSError(error)
    }
  }

  private query(url: string, params: WPSParams) {
    const query = this.ctx.query(params)
    if (url.indexOf('?') > 0) {
      return `${url}&${query}`
    }
    if (query && query.length > 0) {
      return `${url}?${query}`
    }
    return url
  }
}
